package com.xyq.friend.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.PageHelper;
import com.xyq.common.core.constants.CacheConstants;
import com.xyq.common.core.constants.Constants;
import com.xyq.common.core.domain.PageDomain;
import com.xyq.common.core.enums.ExamListType;
import com.xyq.common.core.utils.ThreadLocalUtil;
import com.xyq.common.redis.service.RedisService;
import com.xyq.friend.domain.message.MessageVO;
import com.xyq.friend.domain.message.MessageVO;
import com.xyq.friend.mapper.MessageTextMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class MessageCacheManager {
    @Autowired
    private RedisService redisService ;

    @Autowired
    private MessageTextMapper messageTextMapper  ;

    // 获取用户消息列表key
    private String getUserMessageListKey(Long userId) {
        return CacheConstants.USER_MESSAGE_LIST +userId ;
    }
    // 获取消息详情key
    private String getUserMessageDetailKey(Long messageTextId) {
        return CacheConstants.USER_MESSAGE_DETAIL +messageTextId ;
    }

    public Long getListSize(Long userId) {
         return redisService.getListSize(getUserMessageListKey(userId) );
    }

    public void refreshCache(Long userId) {
        // 刷新当前用户的消息缓存
       List<MessageVO> messageVOList =   messageTextMapper.selectMessageVOList(userId);
       if(CollectionUtil.isEmpty(messageVOList)){
           return;
       }
        List<Long> messageTextIdList = messageVOList.stream().map(MessageVO::getMessageTextId).toList();
        Map<String, MessageVO> messageTextVOMap = new HashMap<>();
        for(MessageVO messageVO : messageVOList){
            messageTextVOMap.put(getUserMessageDetailKey(messageVO.getMessageTextId()),messageVO);
        }
        redisService.multiSet(messageTextVOMap);  //刷新详情缓存
        redisService.deleteObject(getUserMessageListKey(userId)); // 先删除
        redisService.rightPushAll(getUserMessageListKey( userId), messageTextIdList);      //刷新列表缓存
    }


    public List<MessageVO> getMeesageVOList(PageDomain pageDomain, Long userId) {
        // 计算下标处理分页
        int start = (pageDomain.getPageNum() - 1) * pageDomain.getPageSize();
        int end = start + pageDomain.getPageSize() - 1; //下标需要 -1
        // 判断是要 哪个竞赛列表
        String messageListKey = getUserMessageListKey( userId);
        // 获取列表 redis里的列表存储的的是竞赛id
        List<Long> messageIdList = redisService.getCacheListByRange(messageListKey, start, end, Long.class);
        // 通过竞赛id , 获取对应的竞赛
        List<MessageVO> messageVOList = assembleMessageVOList(messageIdList);

        // 如果获取到的列表里有空的 , 就表示数据有问题 ,
        // 而从 MySQL数据库里查
        if (CollectionUtil.isEmpty(messageVOList)) {
            //说明redis中数据可能有问题 从数据库中查数据并且重新刷新缓存
            messageVOList = getExamListByDB(pageDomain , userId); //从数据库中获取数据
            // 查完后同时 refreshCache 刷新一下redis缓存
            refreshCache(userId);
        }
        return messageVOList;
    }

    private List<MessageVO> assembleMessageVOList(List<Long> messageIdList) {
        if (CollectionUtil.isEmpty(messageIdList)) {
            //说明redis当中没数据 从数据库中查数据并且重新刷新缓存
            return null;
        }
        //拼接redis当中key的方法 并且将拼接好的key存储到一个list中
        List<String> detailKeyList = new ArrayList<>();
        for (Long messageDetailId : messageIdList) {
            detailKeyList.add(getUserMessageDetailKey(messageDetailId));
        }
        // 批量获取数据
        List<MessageVO> messageTextVOList = redisService.multiGet(detailKeyList, MessageVO.class);

        // 清除掉 竞赛列表里 为null 的值
        CollUtil.removeNull(messageTextVOList);
        // 如果 竞赛列表里有 null的值 , 就表示 redis里有数据问题
        if (CollectionUtil.isEmpty(messageTextVOList) || messageTextVOList.size() != messageIdList.size()) {
            //说明redis中数据有问题 从数据库中查数据并且重新刷新缓存
            return null;
        }
        return messageTextVOList;
    }

    // 通过MySQL的 接口来获取消息列表
    private List<MessageVO> getExamListByDB(PageDomain pageDomain , Long userId) {
        PageHelper.startPage(pageDomain.getPageNum(), pageDomain.getPageSize());
        return messageTextMapper.selectMessageVOList(userId);
    }

     public void deleteCache(Long messageTextId) {
         Long id = ThreadLocalUtil.get(Constants.USER_ID, Long.class);
         redisService.deleteObject(  getUserMessageDetailKey(messageTextId ));
       redisService.removeForList(getUserMessageListKey(id), messageTextId);
    }
}
